﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

namespace comm
{
    public class TcpServer
    {
        public int AllClientCount { get { return _clientDic.Count; } }

        Dictionary<string, TcpClient> _clientDic = new Dictionary<string, TcpClient>();
        comm.UniqueID _uid = new comm.UniqueID("c");
        Socket _listener = null;

        public Action<TcpClient> OnConnectCallback;

        public TcpServer(string ip, int port)
        {
            try
            {
                _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _listener.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
                _listener.Listen(1000);
                _listener.BeginAccept(new AsyncCallback(EndConnection), null);
            }
            catch (Exception e)
            {
                Console.WriteLine("TcpServer listen " + e.Message);
            }
        }

        public TcpClient GetClient(string clientId)
        {
            TcpClient client = null;
            _clientDic.TryGetValue(clientId, out client);
            return client;
        }

        void EndConnection(IAsyncResult result)
        {
            Socket socket = null;
            var clientId = _uid.NewId();
            try
            {
                socket = _listener.EndAccept(result);
                var client = new TcpClient(socket, clientId, RemoveClient);
                lock (this)
                {
                    _clientDic.Add(clientId, client);
                }
                if (OnConnectCallback != null)
                {
                    OnConnectCallback(client);
                }
                client.BeginReceive();
            }
            catch (Exception)
            {
                try
                {
                    socket.Close();
                }
                catch (Exception)
                {
                }

                RemoveClient(clientId);
            }
            _listener.BeginAccept(new AsyncCallback(EndConnection), null);
        }
        void RemoveClient(string clientId)
        {
            lock (this)
            {
                if (_clientDic.ContainsKey(clientId))
                {
                    _clientDic.Remove(clientId);
                }
            }
        }
    }
}
